﻿#include "WAVWriter.h"
#include "io/ByteBuffer.h"
#include "lang/String.h"
using namespace yzrilyzr_io;
using namespace yzrilyzr_lang;
namespace yzrilyzr_util{
	void WAVWriter::prepare(int32_t sampleRate, int32_t bitsPerSample, int32_t format, int32_t numChannels){
		u_index headerLength=format == FORMAT_FLOAT?FLOAT_HEADER_LENGTH:PCM_HEADER_LENGTH;
		raf.skipBytes(headerLength);
		this->format=format;
		this->bitsPerSample=bitsPerSample;
		this->bytePerSample=bitsPerSample / 8;
		this->numChannels=numChannels;
		this->sampleRate=sampleRate;
		this->byteRate=sampleRate * numChannels * bytePerSample;
		this->blockAlign=numChannels * bytePerSample;
	}
	void WAVWriter::writeFloat(float v){
		raf.writeFloat(v);
	}
	void WAVWriter::writeDouble(double v){
		raf.writeDouble(v);
	}
	void WAVWriter::writeShort(int16_t v){
		raf.writeShort(v);
	}
	void WAVWriter::writeByte(int8_t v){
		raf.writeByte(v);
	}
	void WAVWriter::nextFrame(){
		frames++;
	}
	void WAVWriter::end(){
		int32_t dataChunkSize=frames * numChannels * bytePerSample;
		bool isFloat=(format == FORMAT_FLOAT);
		u_index headerLength=isFloat ? FLOAT_HEADER_LENGTH : PCM_HEADER_LENGTH;
		int chunkSize=dataChunkSize+headerLength-8;
		auto buffer=ByteBuffer::allocate(headerLength);
		buffer->order(ByteOrder::LITTLE_ENDIAN);
		buffer->put(String("RIFF").getBytes());
		buffer->putInt(chunkSize);
		buffer->put(String("WAVE").getBytes());
		buffer->put(String("fmt ").getBytes());
		buffer->putInt(16);
		buffer->putShort((short)format);
		buffer->putShort((short)numChannels);
		buffer->putInt(sampleRate);
		buffer->putInt(byteRate);
		buffer->putShort((short)blockAlign);
		buffer->putShort((short)bitsPerSample);
		if(isFloat){
			buffer->put(String("fact").getBytes());
			buffer->putInt(4);
			buffer->putInt(frames);
		}
		buffer->put(String("data").getBytes());
		buffer->putInt(dataChunkSize);
		raf.seek(0);
		raf.write(buffer->array());
		raf.setLength(headerLength + dataChunkSize);
		raf.close();
	}
}